package wechat

import (
	"context"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
	"github.com/wechatpay-apiv3/wechatpay-go/utils"

	v1 "caas-platform-payment/api/wechat/v1"
	"caas-platform-payment/internal/consts"
	"caas-platform-payment/internal/dao"
	"caas-platform-payment/internal/model/entity"
)

func (c *ControllerV1) MiniPay(ctx context.Context, req *v1.MiniPayReq) (res *v1.MiniPayRes, err error) {

	tenantCode := ctx.Value(consts.TokenClaims.TenantCode).(string)
	// 读取商户信息
	cls := dao.PayChannel.Columns()
	if req.AppId == "" || req.OpenId == "" || req.OutTradeNo == "" || req.TotalFee == 0 {
		l.Error(ctx, req)
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "参数错误")
	}
	ch := &entity.PayChannel{}
	err = dao.PayChannel.Ctx(ctx).Where(cls.TenantCode, tenantCode).Where(cls.AppId, req.AppId).Where(cls.ChannelName, consts.PayChannels[0].Name).Scan(ch)
	if err != nil || ch.Id == 0 {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.MerchantNotFound)
	}
	// 加载私钥
	privateKey, err := utils.LoadPrivateKey(ch.PrivateKey)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.LoadPrivateKeyFailed)
	}
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(ch.MerchantId, ch.MerchantCertSerialNumber, privateKey, ch.MerchantApiKey),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.WechatClientInitFailed)
	}

	svc := jsapi.JsapiApiService{Client: client}

	// 发起支付并返回支付签名
	resp, result, err := svc.PrepayWithRequestPayment(ctx, jsapi.PrepayRequest{
		Appid:       &req.AppId,
		Mchid:       &ch.MerchantId,
		OutTradeNo:  &req.OutTradeNo,
		NotifyUrl:   &ch.PayNotifyUrl,
		Amount:      &jsapi.Amount{Total: &req.TotalFee, Currency: core.String("CNY")},
		Payer:       &jsapi.Payer{Openid: &req.OpenId},
		Description: &req.Description,
	})
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.WechatPayFailed)
	}
	if result.Response.StatusCode != 200 {
		l.Error(ctx, result.Response)
		return nil, gerror.NewCode(consts.WechatPayFailed)
	}
	return &v1.MiniPayRes{
		AppId:     resp.Appid,
		NonceStr:  resp.NonceStr,
		Package:   resp.Package,
		PaySign:   resp.PaySign,
		TimeStamp: resp.TimeStamp,
	}, nil
}
